# zope imports
from zope.component import adapts
from zope.interface import implements
from zope.interface import Interface
from zope.component import getUtility

# CMFPlone imports
from Products.CMFPlone.utils import base_hasattr

# CMFCore imports
from Products.CMFCore.utils import getToolByName
from Products.CMFCore.WorkflowCore import WorkflowException

# xml imports
from xml.sax import handler
from xml.sax import make_parser
from xml.sax import saxutils

# easyshop imports
from iqpp.plone.io.interfaces import IImport
from iqpp.plone.io.interfaces import IContentActions

class Importer:
    """
    """
    implements(IImport)
    adapts(Interface)
    
    def __init__(self, context):
        """
        """
        self.context = context

    def importObjects(self, path):
        """
        """
        parser = make_parser()
        parser.setContentHandler(SAXImporter(self.context, path))
        parser.parse(path)

class SAXImporter(handler.ContentHandler):
    """
    """
    def __init__(self, node, path):
        """
        """
        self.path = path
        self.start_node = node
        self.current_node = node
        self.current_type = None
        self.inner_text = False
        self.inner_description = False
        self.text = ""
        
        self.putils = getToolByName(node, "plone_utils")
        self.wftool = getToolByName(node, "portal_workflow")
        
    def startElement(self, name, attrs):
        """
        """
        if self.inner_text == True:
            self.text += '<' + name
            for (name, value) in attrs.items():
                self.text += ' %s="%s"' % (name, saxutils.escape(value))
            self.text += '>'
        
        if name.lower() == "text":
            self.inner_text = True
            
        elif name.lower() == "description":
            self.inner_description = True

        elif name.lower() == "content":
            self.current_type = attrs["type"]

            # Generate id if there is none
            if attrs.has_key("id") == False:
                id = self.putils.normalizeString(attrs["title"])
            else:
                id = attrs["id"]
            

            # Create content if it isn't exists yet
            if base_hasattr(self.current_node, id) == False:
                id = self.current_node.invokeFactory(attrs["type"], id, title=attrs["title"])

            self.current_node = self.current_node[id]
            
            # Do some content specific actions
            ca = getUtility(IContentActions)
            if hasattr(ca, self.current_type):
                method = getattr(ca, self.current_type)
                method(self.start_node, self.current_node, self.path, name, attrs)
                                
            # Workflow
            if attrs.has_key("state"):
                try:
                    self.wftool.doActionFor(self.current_node, attrs["state"])
                except WorkflowException:
                    pass
            
            # Set default page
            if attrs.has_key("default_page"):
                if self.current_node.hasProperty("default_page") == False:
                    self.current_node.manage_addProperty("default_page", attrs["default_page"], "string")
                
    def endElement(self, name):
        """
        """
        if self.inner_text == True and name != "text":
            self.text += '</%s>' % name
            
        if name.lower() == "text":
            self.inner_text = False
            
        elif name.lower() == "description":
            self.inner_description = False
            
        elif name.lower() == "content":
            try:
                self.current_node.setText(self.text)
            except AttributeError:
                pass

            self.text = ""
            self.current_node = self.current_node.aq_inner.aq_parent

    def characters(self, content):
        """
        """
        content = saxutils.escape(content)
        
        if self.inner_text == True:
            self.text += content
            
        elif self.inner_description == True:
            self.current_node.setDescription(content)

    def ignorableWhitespace(self, content):
        """
        """
        if self.inner_text == True:
            self.text += content
        
    def processingInstruction(self, target, data):
        """
        """
        if self.inner_text == True:
            self.text += '<?%s %s?>' % (target, data)